package com.zjc.gateway.redis;

import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

public class RedisUtils<T> {

    private RedisTemplate<String, T> redisTemplate;

    /**
     * redis的key前缀
     */
    private String prefix;

    public RedisUtils(RedisTemplate<String, T> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public RedisUtils(String prefix, RedisTemplate<String, T> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.prefix = prefix;
    }

    private String createKey(String key) {
        if (!StringUtils.isEmpty(prefix)) {
            key = prefix + key;
        }
        return key;
    }

    /**
     * 往redis中set值
     *
     * @param key
     * @param value
     * @author wujiajun
     */
    public void set(String key, T value) {
        redisTemplate.opsForValue().set(createKey(key), value);
    }

    /**
     * 往redis中set值
     *
     * @param key
     * @param value
     * @param timeout
     * @author wujiajun
     */
    public void set(String key, T value, Long timeout) {
        redisTemplate.opsForValue().set(createKey(key), value, timeout, TimeUnit.SECONDS);
    }


    /**
     * 设置key的有效时间
     *
     * @param key
     * @param timeout
     * @author wujiajun
     */
    public void expire(String key, Long timeout) {
        redisTemplate.expire(createKey(key), timeout, TimeUnit.SECONDS);
    }

    /**
     * 通过key获取value
     *
     * @param key
     * @return
     * @author wujiajun
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key) {
        return (T) redisTemplate.opsForValue().get(createKey(key));
    }

    /**
     * 通过key删除value
     *
     * @param key
     * @author wujiajun
     */
    public void delete(String key) {
        redisTemplate.delete(createKey(key));
    }

    public long increment(String key, long delta) {
        return redisTemplate.opsForValue().increment(createKey(key), delta);
    }

    /**
     * 锁操作
     *
     * @param lockName
     * @param lockValue
     * @param timeout
     * @return
     * @author wujiajun
     */
    public Boolean acquireLock(final String lockName, final String lockValue, final Integer timeout) {
        return redisTemplate.execute((RedisConnection connection) -> {
            byte[] lockNameBytes = redisTemplate.getStringSerializer().serialize(createKey(lockName));
            byte[] lockValueBytes = ((RedisSerializer<String>) redisTemplate.getDefaultSerializer()).serialize(lockValue);
            boolean locked = connection.setNX(lockNameBytes, lockValueBytes);
                    if (locked) {
                        connection.expire(lockNameBytes, timeout);
                        return true;
                    }
                    return false;
                }
        );
    }
}
